package com.sprite.support.wechat.service;

import java.util.*;
import java.util.concurrent.ConcurrentLinkedQueue;

import com.sprite.utils.UtilBeans;
import com.sprite.utils.UtilMisc;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.sprite.support.wechat.bean.req.ReqBaseMessageBean;
import com.sprite.support.wechat.bean.resp.RespBaseMessageBean;
import com.sprite.support.wechat.common.WechatEventConstant;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

/**
 * 消息分发器
 * @author Jack
 */
public final class WechatMessageDispatcher {
	
	private static final Logger logger = LoggerFactory.getLogger(WechatMessageDispatcher.class);
	
	public Map<String, WechatMessageHandler<? extends ReqBaseMessageBean>> handlerMap =new HashMap<String, WechatMessageHandler<? extends ReqBaseMessageBean>>();

	private int recordLimit = 1000;

	// 处理过的请求
	private ConcurrentLinkedQueue<ReqBaseMessageBean> linkedQueue = new ConcurrentLinkedQueue<>();

	public <T extends ReqBaseMessageBean> void setHandlers(List<WechatMessageHandler<T>> handlers) {
		if(handlers != null) {
			for(WechatMessageHandler<T> handler : handlers) {
				handlerMap.put(handler.msgType(), handler);
			}
		}
	}
	
	public RespBaseMessageBean dispatch(String key, Element rootElement) throws Exception {
		WechatMessageHandler<? extends ReqBaseMessageBean> handler = handlerMap.get(key);
		
		if(handler == null) {
			logger.info("[dispatch] not found handler, msgKey:{}", key);
			return null;
		}
		
		ReqBaseMessageBean reqBaseMessageBean = UtilBeans.fromXml(rootElement, handler.msgClass());
		if(!checkRepeat(reqBaseMessageBean)) {
			logger.info("[dispatch] msg has handled, msg:{}", reqBaseMessageBean);
			return null;
		}
		
		RespBaseMessageBean respBaseMessageBean = handler.handle(UtilMisc.cast(reqBaseMessageBean));
		recordHandle(reqBaseMessageBean);
    	return respBaseMessageBean;
	}


	/**
	 * 检查重复性
	 * @param reqBaseMessageBean
	 * @return
	 */
    private boolean checkRepeat(ReqBaseMessageBean reqBaseMessageBean) {
		return !linkedQueue.contains(reqBaseMessageBean);
	}

	/**
	 * 记录处理过的时间
	 * @param reqBaseMessageBean
	 */
	private void recordHandle(ReqBaseMessageBean reqBaseMessageBean){
		if(linkedQueue.size() > this.recordLimit){
			long ct = System.currentTimeMillis()/1000L;
			Iterator<ReqBaseMessageBean> itr = linkedQueue.iterator();
			while (itr.hasNext()){
				ReqBaseMessageBean messageBean = itr.next();
				if(ct - messageBean.getCreateTime() > 15){// 创建时间大于15秒，移除
					itr.remove();
				}
			}
		}

		linkedQueue.add(reqBaseMessageBean);
	}
}
